#ifndef SIMPLE_SUPPORT_META_INTEGER_SEQUENCE_HPP
#define SIMPLE_SUPPORT_META_INTEGER_SEQUENCE_HPP

#include <utility> // std::integer_seuence std::make_index_sequence

namespace simple::support::meta
{

	template <typename Sequence, auto Offset>
	struct offset_sequence;
	template <typename T, auto Offset, T... Is>
	struct offset_sequence<std::integer_sequence<T, Is...>, Offset>
	{ using type = std::integer_sequence<T, (Is + Offset)...>; };
	template <typename Sequence, auto Offset>
	using offset_sequence_t = typename offset_sequence<Sequence, Offset>::type;

	template <auto begin, auto size>
	using make_index_segment = offset_sequence_t<
		std::make_index_sequence<size>, begin >;

	template <auto begin, auto end>
	using make_index_range = make_index_segment<begin,
		(begin < end) ? end - begin : 0>;

	template <typename IntSec, typename OtherIntSec>
	struct concat_sequence;
	template <typename Int, Int... ones, Int... others>
	struct concat_sequence<std::integer_sequence<Int, ones...>, std::integer_sequence<Int,others...>>
	{ using type = std::integer_sequence<Int, ones..., others...>; };
	template <typename A, typename B>
	using concat_sequence_t = typename concat_sequence<A,B>::type;

	template <auto value, typename I>
	struct fill_index_sequence;
	template <auto value, auto... I>
	struct fill_index_sequence<value, std::index_sequence<I...>>
	{ using type = std::index_sequence<(void(I),value)...>; };
	template <auto value, auto size>
	using fill_index_sequence_t = typename fill_index_sequence<value, std::make_index_sequence<size>>::type;

	template <typename IntSec>
	struct reverse_sequence;
	template <typename Int, Int one>
	struct reverse_sequence<std::integer_sequence<Int, one>>
	{ using type = std::integer_sequence<Int, one>; };
	template <typename Int, Int first, Int... rest>
	struct reverse_sequence<std::integer_sequence<Int, first, rest...>>
	{ using type = concat_sequence_t<typename reverse_sequence<std::integer_sequence<Int, rest...>>::type, std::integer_sequence<Int, first>>; };
	template <typename IntSec>
	using reverse_sequence_t = typename reverse_sequence<IntSec>::type;

} // namespace simple::support::meta

#endif /* end of include guard */
